<script setup>
import { Handle, useHandleConnections, useVueFlow } from '@vue-flow/core';
import { NodeToolbar } from '@vue-flow/node-toolbar';
import { defineEmits, reactive, toRef } from 'vue';
import { VsLoadingFn } from 'vuesax-alpha';
import { initCommonNodeProp } from '../../drag/initProp';
import { initEdges } from '../../edge/initEdgeProp';
import NodeIcon from '../../icon/NodeIcon.vue';

const props = defineProps({
  id: {
    type: String,
    required: true,
  },
  data: {
    type: Object,
    required: true,
  },
  sourcePosition: {
    type: String,
  },
  targetPosition: {
    type: String,
  },
})

function uuid() {
  return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
    var r = Math.random() * 16 | 0,
        v = c == 'x' ? r : (r & 0x3 | 0x8);
    return v.toString(16);
  });
}

const emit = defineEmits(['layoutGraph'])

const { addNodes, addEdges, removeNodes, findNode, updateNodeData } = useVueFlow()
const node = findNode(props.id)
const dataRef = ref(props.data)
const id = ref(props.data.id || '')
const name = ref(props.data.name || '')
const nodeDataThen = reactive(props.data.nodeDataThen || {})
const style = reactive(props.data.style || {})

watch(id, val => {  
  node.data.id = val;
})

watch(name, val => {  
  node.data.name = val;
})

watchEffect(() => {
  node.data.nodeDataThen = nodeDataThen
});

const sourceConnections = useHandleConnections({
  type: 'target',
})

const targetConnections = useHandleConnections({
  type: 'source',
})

const isSender = toRef(() => sourceConnections.value.length <= 0)

const isReceiver = toRef(() => targetConnections.value.length <= 0)

const bgColor = toRef(() => {
  if (isSender.value) {
    if (props.data.hasError) {
      return '#f87171'
    }
    if (props.data.isFinished) {
      return '#42B983'
    }
    if (props.data.isCancelled) {
      if (loadingInstance) {
        loadingInstance?.close();
        loadingInstance = null; // 关闭后清空实例
      }
      return '#fbbf24'
    }
    return '#ddd'
  }

  if (props.data.hasError) {
    return '#f87171'
  }

  if (props.data.isFinished) {
    return '#42B983'
  }

  if (props.data.isCancelled) {
    return '#fbbf24'
  }

  return '#ddd'
})

const dialogStyleActive = ref(false)
const counterDanger = ref(false)
const nodeRef = ref(null)

const handleOpacity = computed(() => {
  return style.handles.map(handle => handle.opacity > 0);
});

const setHandleOpacity = (index, value) => {
  style.handles[index].opacity = value ? 1 : 0;
};

const handleOpacityExtend = computed(() => {
  return style.extendHandles.map(handle => handle.opacity > 0);
});

const setHandleOpacityExtend = (index, value) => {
  style.extendHandles[index].opacity = value ? 1 : 0;
};

const handleStyle = ref();
const handleStyleText = ref()
const dialogStyleClick = (handle) => {
  dialogStyleActive.value = true;
  handleStyleText.value = handle.style;
  handleStyle.value = handle;
};

watch(handleStyleText, val => {  
  handleStyle.value.style = val;
  nextTick(() => {
    updateNodeInternals([props.id]);
  });
})

const modeDefault = ref(true)
let loadingInstance = null; 
// 直接使用 props.data，因为 props 本身是响应式的
onMounted(() => {
  watch(() => props.data.isRunning, (newVal, oldVal) => {
    if (newVal) {
      if(modeDefault.value){
        loadingInstance = VsLoadingFn({
          target: nodeRef,
          text: 'Loading...',
        });
      }else{
        loadingInstance = VsLoadingFn({
          target: nodeRef,
        });
      }
    } else {
      if (loadingInstance) {
        loadingInstance?.close();
        loadingInstance = null; // 关闭后清空实例
      }
    }
  }, { immediate: true }); // immediate: true 选项可以在初次绑定时立即执行一次回调

  watch(() => props.data, (newVal, oldVal) => {
    if (newVal.mode == 'default') {
      modeDefault.value = true
    } else {
      modeDefault.value = false
    }
    id.value = newVal.id
    name.value = newVal.name
  }, { immediate: true, deep: true }); 

  if(id.value == ''){
    id.value = uuid();
  }
});



const addLeftPoint = () => {
  style.extendHandles.push(...[{id: uuid(), position: 'left', opacity: 1, type: 'source', style: 'top:10px;left:0px;'}])
};

const addRightPoint = () => {
  style.extendHandles.push(...[{id: uuid(), position: 'right', opacity: 1, type: 'source', style: 'top:10px;right:0px;'}])
};

const addTopPoint = () => {
  style.extendHandles.push(...[{id: uuid(), position: 'top', opacity: 1, type: 'source', style: 'top:0px;left:10px;'}])
};

const addBottomPoint = () => {
  style.extendHandles.push(...[{id: uuid(), position: 'bottom', opacity: 1, type: 'source', style: 'bottom:0px;left:10px'}])
};


//编辑器
const popupDataJson = ref(false)
const options = ref({
  colorDecorators: true,
  lineHeight: 24,
  tabSize: 2,
})

// Toolbar
const addParentNodeClick = () => {
  const node = findNode(props.id)
  const nodeData = JSON.parse(JSON.stringify(node));
  const uid = uuid();
  nodeData.data.id = uid;

  const newNode = {
    id: uid,
    type: nodeData.type,
    position: {
      x: nodeData.position.x - 450,
      y: nodeData.position.y
    },
    label: nodeData.label,
    data: nodeData.data
  }
  addNodes([newNode])
  addEdges(initEdges(newNode.id, nodeData.id))
  emit('layoutGraph', 'LR')
}

const addChildNodeClick = () => {
  const node = findNode(props.id)
  const nodeData = JSON.parse(JSON.stringify(node));
  const uid = uuid();
  nodeData.data.id = uid;

  const newNode = {
    id: uid,
    type: nodeData.type,
    position: {
      x: nodeData.position.x + 450,
      y: nodeData.position.y
    },
    label: nodeData.label,
    data: nodeData.data
  }
  addNodes([newNode])
  addEdges(initEdges(nodeData.id, newNode.id))
  emit('layoutGraph', 'LR')
}

const copyNodeClick = () => {
  const node = findNode(props.id)
  const nodeData = JSON.parse(JSON.stringify(node));
  const uid = uuid();
  nodeData.data.id = uid;
  const newNode = {
    id: uid,
    type: nodeData.type,
    position: {
      x: nodeData.position.x,
      y: nodeData.position.y + 300
    },
    label: nodeData.label,
    data: nodeData.data
  }

  nextTick(() => {
    addNodes([newNode])
  })
}

const resetNodePropClick = () => {
  const json = initCommonNodeProp();
  id.value = uuid()
  name.value = json.name
  Object.keys(nodeDataThen).forEach(key => {
    delete nodeDataThen[key]; // 删除所有属性
  });
}

const resetNodeStyleClick = () => {
  const json = initCommonNodeProp();
  style.handles = []
  nextTick(() => {
    style.handles = json.style.handles
    style.extendHandles = json.style.extendHandles
  })
}

const removeNodeClick = () => {
  removeNodes(props.id)
}
</script>

<template>
  <vs-tooltip
      v-model="activeTooltip1"
      placement="bottom"
      type="shadow"
      trigger="click"
    >
    <div ref="nodeRef" class="when-node" :style="{ borderWidth: '1px', borderColor: bgColor}">
      <NodeToolbar v-if="false" :is-visible="dataRef.style.toolbar.isVisible" :position="dataRef.style.toolbar.position" :offset="dataRef.style.toolbar.offset">
        <vs-tooltip placement="top">
          <vs-button color="#195bff" shape="circle" icon type="floating" @click="addParentNodeClick">
            <vs-icon v-if="dataRef.style.toolbar.showIcon" size="30">
              <vs-icon-plus />
            </vs-icon>
          </vs-button>
          <template #content> 插入父节点 </template>
        </vs-tooltip>
        
        <vs-tooltip placement="top">
          <vs-button shape="circle" icon type="floating" @click="addChildNodeClick">
            <vs-icon v-if="dataRef.style.toolbar.showIcon" size="30">
              <vs-icon-plus />
            </vs-icon>
          </vs-button>
          <template #content> 插入子节点 </template>
        </vs-tooltip>

        <vs-tooltip placement="top">
          <vs-button color="whatsapp" shape="circle" icon type="floating" @click="copyNodeClick">
            <vs-icon v-if="dataRef.style.toolbar.showIcon" size="30">
              <vs-icon-Pause />
            </vs-icon>
          </vs-button>
          <template #content> 复制节点 </template>
        </vs-tooltip>
        
        <vs-tooltip placement="top">
          <vs-button color="#ff8200" shape="circle" icon type="floating" @click="resetNodePropClick">
            <vs-icon v-if="dataRef.style.toolbar.showIcon" size="30">
              <vs-icon-trash />
            </vs-icon>
          </vs-button>
          <template #content> 重置属性 </template>
        </vs-tooltip>
        
        <vs-tooltip placement="top">
          <vs-button color="#ff8200" shape="circle" icon type="floating" @click="resetNodeStyleClick">
            <vs-icon v-if="dataRef.style.toolbar.showIcon" size="30">
              <vs-icon-trash />
            </vs-icon>
          </vs-button>
          <template #content> 重置样式 </template>
        </vs-tooltip>
        
        <vs-tooltip placement="top">
          <vs-button color="#ff3e4e" shape="circle" icon type="floating" @click="removeNodeClick">
            <vs-icon v-if="dataRef.style.toolbar.showIcon" size="30">
              <vs-icon-trash />
            </vs-icon>
          </vs-button>
          <template #content> 删除节点 </template>
        </vs-tooltip>
      </NodeToolbar>
      
      <NodeIcon :name="dataRef.type" />

      <div>
        <Handle
          v-for="(handle,index) in style.handles"
          :key="index"
          :id="handle.id"
          :class="[
            handle.type == 'source'? 'handle-when-node-source':'handle-when-node-target'
          ]"
          :type="handle.type"
          :position="handle.position"
          :style="[handle.style, { opacity: handle.opacity }]"
        >
        </Handle>
      </div>
    </div>
    <template #content>
      <div class="content-tooltip">
        <vs-divider>AND属性设置</vs-divider>
        <!-- 
        <vs-input
          v-model="nodeDataThen.id"
          class="w-100 nodrag"
          color="success" 
          label="表达式ID" 
          label-float 
        />

        <vs-checkbox v-model="nodeDataThen.isCatch"> 捕获异常(CATCH) </vs-checkbox>

        <vs-input
          v-if='nodeDataThen.isCatch'
          v-model="nodeDataThen.catchDo"
          class="w-100 nodrag"
          color="success" 
          label="CATCH DO组件" 
          label-float 
        />


        <div class="div-ignore-type">
          <vs-radio v-model="nodeDataThen.ignoreType" value="not"> 不忽略其他 </vs-radio>
          <vs-radio v-model="nodeDataThen.ignoreType" value="any"> 任一节点先执行完则忽略其他(any) </vs-radio>
          <vs-radio v-model="nodeDataThen.ignoreType" value="must"> 指定任意节点先执行完则忽略其他(must) </vs-radio>
        </div> -->

        
      </div>
    </template>
  </vs-tooltip>
  
</template>

<style scoped>
.when-node {
  padding: 5px;
  border-radius: 5px;
  background-color: #fff;
  block-size: 36px;
  inline-size: 36px;
}

.when-node-title .icon-with-text{
  border: 0 !important;
  padding-inline: 0;
}

.div-ignore-type{
  margin-block-start: 8px;
}

.div-ignore-type div{
  margin-block-end: 8px;
}
</style>

<style>
/* .handle-node-left,.handle-node-right{
  border-radius: 4px !important;
  block-size: 24px !important;
  inline-size: 12px !important; 
}

.handle-node-top,.handle-node-bottom{
  border-radius: 4px !important;
  block-size: 12px !important;
  inline-size: 24px !important; 
}
*/

/* .handle-when-node-source{
  background-color: #c8d8fc !important;
}

.handle-when-node-target{
  background-color: #ff9fa7 !important;
}  */

.vue-flow__node-toolbar {
  display: flex;
  align-items: center;
  padding: 8px;
  border-radius: 8px;
  gap: 0.5rem;
}

</style>
